/**
 * 
 */
package algoritmo;

import java.sql.Date;
import java.sql.Time;
import java.util.ArrayList;

import aplicacion.datos.Turno;
import aplicacion.utilidades.Util;
import java.util.ResourceBundle;

/**
 * @author Alberto
 * Esta clase analiza el cuadrante creado buscando errores a la hora de asignar
 * a los empleados, creando un informe final que se le presenta al jefe de departamento
 */
public class Analisis {
	private ArrayList<Sugerencia>[] sugerencias;
	private int dias;
	private ResourceBundle bundle;
	
	/**
	 * Constructora con parámetros
	 * @param dias Dias a analizar
	 * @param cuadrante Cuadrante que ha sido generado
	 * @param estructura Estructura correspondiente al mes
	 * @param turnos Lista de los turnos del departamento
	 */
	public Analisis (int dias, Cuadrante cuadrante, Calendario cal, ArrayList<Turno> turnos, ResourceBundle bundle){
		this.sugerencias=new ArrayList[dias];
		this.dias=dias;
		this.bundle=bundle;
		for (int i=0;i<dias;i++)
			sugerencias[i]=new ArrayList<Sugerencia>();			
		recorrido(cuadrante,cal,turnos);
	}
	 
	/**
	 * Método para ver faltas de personal del cuadrante generado
	 * @param cuadrante Cuadrante generado
	 * @param estructura Estructura correspondiente
	 * @param turnos Lista de los turnos del departamento
	 */
	public void recorrido (Cuadrante cuadrante, Calendario calendario, ArrayList<Turno> turnos){
		for (int i=0;i<dias;i++){
			//si el dia i no abre el centro, no se calcula el cuadrante
			if ((!calendario.diaLibre(i)) && (cuadrante.getListaTrabajaDia(i).size()!=0)) {
				Time t=new Time(8,0,0);
				for (int j=0;j<24;j++){
					t.setHours(j);
					
					for (int k=0;k<60;k=k+5){
						t.setMinutes(k);
						int minimoDia=calendario.getMinHora(i, j);
						Sugerencia sugAnterior=null;
						//si ya hay alguna sugerencias del dia, se coge la ultima, si no se queda null
						if (!sugerencias[i].isEmpty()){
							if (sugerencias[i].get(sugerencias[i].size()-1).getHoraFin().equals(new Time(t.getHours(),t.getMinutes(),0)))
								sugAnterior=sugerencias[i].get(sugerencias[i].size()-1);
						}
						
						//se comprueba cuantos trabajadores hay en un minuto concreto
						//se hacen franjas de 5 minutos
						int contador=0;
						for (int l=0;l<cuadrante.getListaTrabajaDia(i).size();l++){
							Trabaja trab=cuadrante.getListaTrabajaDia(i).get(l);
							if(compruebaHora(t,buscaTurno(trab.getIdTurno(),turnos))){
								contador++;
							}
						}						
											
						// si el contador es menor que el minimo para ese minuto, se crea una sugerencia nueva
						// solo si no existia una anterior con las mismas caracteristas
						// en caso contrario, se amplia en 5 minutos la franja de la sugerencia
						if (contador<minimoDia){
							if ((sugAnterior!=null)&&((minimoDia-contador!=sugAnterior.getFaltas())||(sugAnterior.getTipo()!=tipoFalta(contador,minimoDia)))){		
								Sugerencia sug=new Sugerencia(minimoDia-contador,minimoDia,new Time(t.getHours(),t.getMinutes(),0),new Time(t.getHours(),t.getMinutes()+5,0),new Date (cuadrante.getAnio()-1900,cuadrante.getMes()-1,i+1),tipoFalta(contador,minimoDia),cuadrante.getIdDepartamento(),bundle);
								sugerencias[i].add(sug);
							} else {
								if (sugAnterior==null) {
									Sugerencia sug=new Sugerencia(minimoDia-contador,minimoDia,new Time(t.getHours(),t.getMinutes(),0),new Time(t.getHours(),t.getMinutes()+5,0),new Date (cuadrante.getAnio()-1900,cuadrante.getMes()-1,i+1),tipoFalta(contador,minimoDia),cuadrante.getIdDepartamento(),bundle);
									sugerencias[i].add(sug);
								} else 
									sugAnterior.ampliar(0,5);
							}
						}										
					}					
				}	
			}
		}
	}
	
	/**
	 * Método para ver faltas de personal de un dia del cuadrante generado
	 * @param dia Dia para el que se quieren las faltas
	 * @param cuadrante Cuadrante generado
	 * @param calendario Calendario correspondiente
	 */
	/*public void recorridoDia (int dia, Cuadrante cuadrante, Calendario calendario){
		//si el dia i no abre el centro, no se calcula el cuadrante
		if ((!calendario.diaLibre(dia)) && (cuadrante.getListaTrabajaDia(dia).size()!=0)) {
			Time t=new Time(8,0,0);
			for (int j=0;j<24;j++){
				t.setHours(j);
				
				for (int k=0;k<60;k=k+5){
					t.setMinutes(k);
					int minimoDia=calendario.getMinHora(dia, j);
					Sugerencia sugAnterior=null;
					//si ya hay alguna sugerencias del dia, se coge la ultima, si no se queda null
					if (!sugerencias[0].isEmpty()){
						if (sugerencias[0].get(sugerencias[0].size()-1).getHoraFin().equals(new Time(t.getHours(),t.getMinutes(),0)))
							sugAnterior=sugerencias[0].get(sugerencias[0].size()-1);
					}
					
					//se comprueba cuantos trabajadores hay en un minuto concreto
					//se hacen franjas de 5 minutos
					int contador=0;
					for (int l=0;l<cuadrante.getListaTrabajaDia(dia).size();l++){
						Trabaja trab=cuadrante.getListaTrabajaDia(dia).get(l);
						if(compruebaHora(t,trab.getFichIni(),trab.getFichFin())){
							contador++;
						}
					}						
										
					// si el contador es menor que el minimo para ese minuto, se crea una sugerencia nueva
					// solo si no existia una anterior con las mismas caracteristas
					// en caso contrario, se amplia en 5 minutos la franja de la sugerencia
					if (contador<minimoDia){
						if ((sugAnterior!=null)&&((minimoDia-contador!=sugAnterior.getFaltas())||(sugAnterior.getTipo()!=tipoFalta(contador,minimoDia)))){		
							Sugerencia sug=new Sugerencia(minimoDia-contador,minimoDia,new Time(t.getHours(),t.getMinutes(),0),new Time(t.getHours(),t.getMinutes()+5,0),new Date (cuadrante.getAnio()-1900,cuadrante.getMes()-1,dia+1),tipoFalta(contador,minimoDia),cuadrante.getIdDepartamento());
							sugerencias[0].add(sug);
						} else {
							if (sugAnterior==null) {
								Sugerencia sug=new Sugerencia(minimoDia-contador,minimoDia,new Time(t.getHours(),t.getMinutes(),0),new Time(t.getHours(),t.getMinutes()+5,0),new Date (cuadrante.getAnio()-1900,cuadrante.getMes()-1,dia+1),tipoFalta(contador,minimoDia),cuadrante.getIdDepartamento());
								sugerencias[0].add(sug);
							} else 
								sugAnterior.ampliar(0,5);
						}
					}										
				}					
			}	
		}
	}*/
	
	/**
	 * Método para analizar las faltas de personal y generar el mensaje correspondiente
	 * @return ArrayList de comentarios con respecto a la falta de personal
	 */
	public ArrayList<String> analizarFaltas(){
		ArrayList<String> resul=new ArrayList<String>();
		int cont1=0;
		int cont2=0;
		int cont3=0;
		for (int i=0;i<dias;i++){			
			if (calcularValorFranja(getSugerenciasDia(i),1)>=0.5){cont1++;}
			if (calcularValorFranja(getSugerenciasDia(i),2)>=0.5){cont2++;}
			if (calcularValorFranja(getSugerenciasDia(i),3)>=0.5){cont3++;}
		}
		if(cont1>=5)
		{
			resul.add(bundle.getString("Faltas_mañana"));
		}
		if(cont2>=6)
		{
			resul.add(bundle.getString("Faltas_mediodia"));
		}
		if(cont3>=6)
		{
			resul.add(bundle.getString("Faltas_tarde"));
		}
		return resul;
	}
	
	/**
	 * Método para calcular el valor de las faltas de personal de un día
	 * @param lista Lista de las sugerencias de un día
	 * @param parte Parte del día para la que se calcula el valor
	 * @return Puntuación del día
	 */
	public double calcularValorFranja(ArrayList<Sugerencia> lista,int parte){
		double resul=0;
		for (int i=0;i<lista.size();i++){
			int horaIni=lista.get(i).getHoraIni().getHours();
			int horaFin=lista.get(i).getHoraFin().getHours();
			switch (parte){
				case 1: if (horaIni<13){resul=resul+lista.get(i).puntuacion();} break;
				case 2: if (((horaIni>=13)&&(horaIni<18))||((horaFin>=13)&&(horaFin<18))){resul=resul+lista.get(i).puntuacion();} break;
				case 3: if (horaIni>=18){resul=resul+lista.get(i).puntuacion();} break;
			}						
		}
		return resul;
	}
	
	/**
	 * Indica si una hora se encuentra incluida dentro de un perido de tiempo
	 * @param a Hora a comprobar
	 * @param ini Hora incial del periodo de tiempo
	 * @param fin Hora final del periodo de tiempo
	 * @return true si la hora está incluida dentro del periodo de tiempo
	 */
	public boolean compruebaHora(Time a, Time ini, Time fin){
		boolean resultado=true;
		if (a.before(ini)){resultado=false;}
		if (a.after(fin) || a.compareTo(fin)==0){resultado=false;}
		return resultado;
	}
	
	/**
	 * Indica si una turno comprende una hora
	 * @param a Hora a comprobar
	 * @param t Turno para comprobar la hora
	 * @return true si el turno comprende la hora
	 */
	public boolean compruebaHora(Time a, Turno t){
		boolean resultado=true;
		//Comparamos con las horas iniciales y finales del turno
		if (a.before(t.getHoraEntrada())){resultado=false;}
		if (a.after(t.getHoraSalida()) || a.compareTo(t.getHoraSalida())==0){resultado=false;}
		//Comparamos con las horas iniciales y finales del descanso
		Time finDescanso = Util.calculaFinDescanso(t.getHoraDescanso(),t.getTDescanso());
		if ((a.after(t.getHoraDescanso()) || a.compareTo(t.getHoraDescanso())==0) && a.before(finDescanso)){resultado=false;}
		return resultado;
	}
	
	/**
	 * Indica el tipo de falta dependiendo de la gente que falta durante una franja de datos
	 * @param contador Número de personas que faltan durante una franja de tiempo
	 * @param minimo Valor mínimo del día
	 * @return El tipo de la falta
	 */
	public int tipoFalta(int contador, int minimo){
		int tipo=0;
		if (contador==0){tipo=2;}
		else {if (contador<=minimo/2){tipo=1;}}
		return tipo;
	}
	
	/**
	 * Consulta las sugerencias de un día
	 * @param i Día del que se piden las sugerencias
	 * @return Sugerencias del día
	 */
	public ArrayList<Sugerencia> getSugerenciasDia(int i){
		return sugerencias[i];
	}
	
	/**
	 * Genera cadenas de texto de sugerencias para cada día
	 * @return Sugerencias para cada día
	 */
	public ArrayList<Sugerencia>[] generarResumen(){
		for (int i=0;i<dias;i++){
			for (int j=0;j<getSugerenciasDia(i).size();j++){
				sugerencias[i].get(j).generarResumen();
			}
		}	
		return sugerencias;
	}
	
	/**
	 * Método que devuelve el turno correspondiente al idTurno indicado
	 * @param idTurno Identificador del turno deseado
	 * @param listaTurnos Lista de todos los turnos del departamento
	 * @return el turno buscado
	 */
	private Turno buscaTurno(int idTurno, ArrayList<Turno> listaTurnos) {
		boolean encontrado = false;
		int n = 0;
		Turno t = null;
		while(!encontrado && n<listaTurnos.size()){
			t = listaTurnos.get(n);
			if(idTurno == t.getIdTurno())
				encontrado = true;			
			n++;
		}
		return t;
	}
	
}
